/* PR c/102989 */
/* { dg-do run { target bitint } } */
/* { dg-options "-std=c23 -pedantic-errors" } */
/* { dg-skip-if "" { ! run_expensive_tests }  { "*" } { "-O0" "-O2" } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */

#if __BITINT_MAXWIDTH__ >= 156
struct S156 { unsigned _BitInt(156) a : 135; _BitInt(156) b : 2; };
struct T156 { _BitInt(156) a : 2; unsigned _BitInt(156) b : 135; _BitInt(156) c : 2; };

__attribute__((noipa)) _BitInt(156)
test156 (struct S156 *p, struct T156 *q, struct T156 *r, int n)
{
  r[0].b = p[0].a + q[0].b;
  r[1].b = p[1].a * q[1].b;
  r[2].a = p[2].a == q[2].b;
  r[3].a = p[3].a < q[3].b;
  r[4].b = p[4].a << n;
  return p[5].a + q[5].b;
}
#endif

#if __BITINT_MAXWIDTH__ >= 495
struct S495 { unsigned _BitInt(495) a : 471; _BitInt(495) b : 2; };
struct T495 { _BitInt(495) a : 2; unsigned _BitInt(495) b : 471; _BitInt(495) c : 2; };

__attribute__((noipa)) _BitInt(495)
test495 (struct S495 *p, struct T495 *q, struct T495 *r, int n)
{
  r[0].b = p[0].a + q[0].b;
  r[1].b = p[1].a * q[1].b;
  r[2].a = p[2].a == q[2].b;
  r[3].a = p[3].a < q[3].b;
  r[4].b = p[4].a << n;
  return p[5].a + q[5].b;
}
#endif

#if __BITINT_MAXWIDTH__ >= 575
struct T575 { _BitInt(575) a : 2; _BitInt(575) b : 382; _BitInt(575) c : 2; };

__attribute__((noipa)) _BitInt(575)
test575 (struct T575 *q, _BitInt(575) x)
{
  return q->b + x;
}
#endif

int
main ()
{
#if __BITINT_MAXWIDTH__ >= 156
  static struct S156 p156[] = {
    { 6086908847973295618751425718189955476089uwb, 0wb },
    { 22782605434509677806291360175224474025979uwb, 1wb },
    { 37470702016132547913133822619863997855935uwb, -1wb },
    { 35506973813062189967442086745146532460068uwb, -2wb },
    { 30541197841349399254932135707861871578815uwb, -2wb },
    { 42800615576623455179183425579556615564998uwb, 1wb },
    { 83771790414073692613953222993102430597uwb, 0wb },
    { 36412564746565547536452588666710660799602uwb, 1wb },
    { 33301340481967309644890101787523367044846uwb, -1wb },
    { 12245185680611854260212331160624126801841uwb, -2wb },
    { 35828279900949208432533857460683046288424uwb, -1wb },
    { 4123278359205456806488911776768785478962uwb, 1wb }
  };
  static struct T156 q156[] = {
    { -2wb, 20935792668463008606182638244678610336415uwb, 0wb },
    { -1wb, 209336580249060835473242979959042853484uwb, -1wb },
    { 0wb, 26553091584512375040647771207085289684805uwb, -2wb },
    { 1wb, 8584102019879028804166913978503267690027uwb, 1wb },
    { -2wb, 3364986457594728242491236670969190237662uwb, 0wb },
    { 1wb, 28487958103578401823549712846248514887291uwb, -1wb },
    { 1wb, 30323438060061607929914857363700386658179uwb, -2wb },
    { -2wb, 38436123658875864126535628489050345446219uwb, 1wb },
    { -1wb, 33301340481967309644890101787523367044846uwb, -1wb },
    { 0wb, 18081372790322879821963779970917788200718uwb, 0wb },
    { 1wb, 35310198378318023568520640435634029391465uwb, -2wb },
    { -2wb, 16532060682830030166332649597929082719904uwb, -1wb }
  };
  struct T156 r156[12];
  static unsigned _BitInt(135) e156[] = {
    27022701516436304224934063962868565812504uwb,
    29613894605882195495382184794066465590244uwb,
    0uwb,
    0uwb,
    25008039169844990156837660987808592822272uwb,
    27732430714321733679421188674538799385921uwb,
    30407209850475681622528810586693489088776uwb,
    9125928536800138281422179636318960655206uwb,
    1uwb,
    1uwb,
    27059094310193532424702800326126974533632uwb,
    20655339042035486972821561374697868198866uwb
  };
  for (int i = 0; i < 12; ++i)
    {
      r156[i].a = (i & 1) ? 1wb : -2wb;
      r156[i].b = (i & 1) ? 14518714321960041107770649917088777022122uwb : 29037428643920082215541299834177554044245uwb;
      r156[i].c = (i & 1) ? -2wb : 1wb;
    }
  r156[5].b = test156 (&p156[0], &q156[0], &r156[0], 17);
  r156[11].b = test156 (&p156[6], &q156[6], &r156[6], 117);
  for (int i = 0; i < 12; ++i)
    if ((((i % 6) - 2U <= 1U) ? r156[i].a : r156[i].b) != e156[i])
      __builtin_abort ();
    else if ((((i % 6) - 2U > 1U) && r156[i].a != ((i & 1) ? 1wb : -2wb))
	     || (((i % 6) - 2U <= 1U) && r156[i].b != ((i & 1) ? 14518714321960041107770649917088777022122uwb : 29037428643920082215541299834177554044245uwb))
	     || r156[i].c != ((i & 1) ? -2wb : 1wb))
      __builtin_abort ();
#endif
#if __BITINT_MAXWIDTH__ >= 495
  static struct S495 p495[] = {
    { 5900641461698162830220261443910312286116186030711054026202132317287171989449954433727605565187406942318472276126021616097079737645240098454013uwb, 0wb },
    { 5619335266199392590390116416034736345432323405939461237257863293465693217703812518219356211176818397041537700744525965483063880249177661765822uwb, -1wb },
    { 744675643612988167093151199551285556694415176163561012938968935653355128760309622135847398882788196739068398576440472762370028310765535983503uwb, 1wb },
    { 4710120587609940729927891635083547264060530096467790505615232580303577049694742313824211264116793595223025831432779325089965241897060863692416uwb, -2wb },
    { 4700240735957362687308898816111021174982406591648489926246999776223031821022674194534613241738369983608058217658021289655774135981827101958355uwb, -1wb },
    { 1876262100946684033144524627883805711239772124030259629263615724983251183045150901527994496938087455223125779829665212386349414296844947524925uwb, 0wb },
    { 2635441776228543412090459941414006837629084474712903013295503578947861806271451688519107975488661564459243720565422264844084425272156107387136uwb, 1wb },
    { 2630153258749552262848995430888671592867309014306367216498408256861265344131972108995527284590063838830515851856437258905217521364301962720643uwb, -2wb },
    { 2745338434240621337939928605056928843351970485626602387969150293308450866745407501724727739848971206349186529783705440219203189970551219879381uwb, 1wb },
    { 2688974451781009079406742432598239379065348006788221659938456041627730645258351669705421830999330571339577238631004906071154604486839621759962uwb, -1wb },
    { 4974200409958136921019163732486769139044513968318459321751943678326303994594283963911023171617076265195547773578798591476134329493900866070930uwb, -2wb },
    { 5308892348567193242289576342108929297198516978578910066291782408432432101971103786646801744963140659914127252602243854634890888430591500677669uwb, 0wb }
  };
  static struct T495 q495[] = {
    { 0wb, 4301604554146816407338627211447119428992719156607107928889754501636100741327050147838502142108071735464603549268761292458205988617578325763173uwb, -2wb },
    { -1wb, 2715194601730000102297343743781623149283369741076005412784114057373119142888076403665408178274328506558203084450300859444566357959934633829946uwb, -1wb },
    { -2wb, 744675643612988167093151199551285556694415176163561012938968935653355128760309622135847398882788196739068398576440472762370028310765535983503uwb, 0wb },
    { 1wb, 2905575297593112682176271367301360286079539486548283169761776505152778266677295498111968142984117916873706310434203454796302860902084876845657uwb, 1wb },
    { -2wb, 1837917528781539509450058185492923533367227689379651913582946492506072644598679412452807791857307066254676899775684162126897712525287848351976uwb, -2wb },
    { -1wb, 2319680246150988952074978951387405463389161562155916967834748191217991286707290863021474691040798411643120909475843121856853198824610064919029uwb, -1wb },
    { 0wb, 995091385198857217634636856758679675740255626224651591597840191331701102225958567078470825514618566121501749811346910563358603344922083332530uwb, 0wb },
    { 1wb, 1935767072657166967374130326547364176008146414333487504728787607207566058414790635912675474199093488415105292641061350133643468776770358124726uwb, 1wb },
    { -1wb, 2323578462079768493720340989036535936419394491913499982954052044299468738290318204298367303716254084159730145465632640799602734853085685711959uwb, -1wb },
    { 0wb, 3134743387837581735890167538039234659353143305621277824366534871456819272038615182289564667918939704822338586693965843434870517084569520632192uwb, 1wb },
    { -2wb, 6069214031750054027161180881734548627596253190931156326304738913835931214674310539698411833298960086513572699541120829870803305974299213978797uwb, -2wb },
    { 1wb, 3475118701665891960802877416318617212624733636229950713368672781946851382777667645205965216548373630879140490108440746796343158443948723601215uwb, 0wb }
  };
  struct T495 r495[12];
  static unsigned _BitInt(471) e495[] = {
    4105080878509056910641706565917653774193674439925640176070095882154968553394649854768634849749595921611538850548285598212613898764208491978338uwb,
    4272455060900825442658035799123612713461581925816375155025420465351224978751666594799676382302564435552275519560187020810679530912731598360332uwb,
    1uwb,
    0uwb,
    193936707178394586072944129724741337251602515686017126954836162236154016065720970574348980545042390967692432385246117380757295497134607826944uwb,
    4195942347097672985219503579271211174628933686186176597098363916201242469752441764549469187978885866866246689305508334243202613121455012443954uwb,
    3630533161427400629725096798172686513369340100937554604893343770279562908497410255597578801003280130580745470376769175407443028617078190719666uwb,
    3017199903252810774645258484587879229328468140025245420287647204420639096996138928094942159316263828975261069022192893745856107126530044652322uwb,
    0uwb,
    1uwb,
    4881485695834897810379845656011652834144895329454510745024612553531749469753415260371487385803388022234443037087409795804654957238790836453376uwb,
    2686845912897162876175271668987768568908019867416339000638664253610979307366416705055294103965631534621730767864187291088562219375930292040036uwb
  };
  for (int i = 0; i < 12; ++i)
    {
      r495[i].a = (i & 1) ? 1wb : -2wb;
      r495[i].b = (i & 1) ? 4064776758223948217944788059626518627276820498261681186014527291178869451588236484531648571697255170781024649897664873561781218332406621492565uwb : 2032388379111974108972394029813259313638410249130840593007263645589434725794118242265824285848627585390512324948832436780890609166203310746282uwb;
      r495[i].c = (i & 1) ? -2wb : 1wb;
    }
  r495[5].b = test495 (&p495[0], &q495[0], &r495[0], 17);
  r495[11].b = test495 (&p495[6], &q495[6], &r495[6], 117);
  for (int i = 0; i < 12; ++i)
    if ((((i % 6) - 2U <= 1U) ? r495[i].a : r495[i].b) != e495[i])
      __builtin_abort ();
    else if ((((i % 6) - 2U > 1U) && r495[i].a != ((i & 1) ? 1wb : -2wb))
	     || (((i % 6) - 2U <= 1U) && r495[i].b != ((i & 1) ? 4064776758223948217944788059626518627276820498261681186014527291178869451588236484531648571697255170781024649897664873561781218332406621492565uwb : 2032388379111974108972394029813259313638410249130840593007263645589434725794118242265824285848627585390512324948832436780890609166203310746282uwb))
	     || r495[i].c != ((i & 1) ? -2wb : 1wb))
      __builtin_abort ();
#endif
#if __BITINT_MAXWIDTH__ >= 575
  struct T575 q575[] = {
    { 0wb, 96684809381001318096256993724350755663760586347837309196134430400012751231961429238828670682891585656560169817843wb, -2wb },
    { -1wb, -2736587102891263842950610428227571747319762162345429601728737031966764668220310874246707348170368842425752759862563wb, 1wb }
  };
  if (test575 (&q575[0], -20620110861486347200204305994458440394552720887062830768778333216240622422772611435913937143052282943196256683484434522946545384240670168537704102522242938522404309878852322wb)
      != -20620110861486347200204305994458440394552720887062830768778236531431241421454515178920212792296619182609908846175238388516145371489438207108465273851560046936747749709034479wb)
    __builtin_abort ();
  if (test575 (&q575[1], 42621052848920155042866550876502212956983884683310087431575669593007353224147609487103322505341199223508939436382180596125666953651582557283994756434373621037386194691552808wb)
      != 42621052848920155042866550876502212956983884683310087431572933005904461960304658876675094933593879461346594006780451859093700188983362246409748049086203252194960441931690245wb)
    __builtin_abort ();
#endif
}
